<template>
  <div class="home-container">
    <!-- 侧边栏 -->
    <el-aside width="200px" class="sidebar">
      <div class="sidebar-user-info">
        <el-dropdown trigger="click">
          <div class="user-avatar">
            <el-avatar :size="40" :src="userAvatar" />
            <span class="username">{{ username }}</span>
          </div>
          <el-dropdown-menu slot="dropdown">
            <el-dropdown-item @click.native="$router.push('/profile')">个人信息管理</el-dropdown-item>
            <el-dropdown-item divided @click.native="handleLogout">退出登录</el-dropdown-item>
          </el-dropdown-menu>
        </el-dropdown>
      </div>
      <el-menu
        :default-active="activeView"
        class="el-menu-vertical"
        background-color="#304156"
        text-color="#bfcbd9"
        active-text-color="#fff"
        @select="handleMenuSelect">
        <el-menu-item index="dashboard">
          <i class="el-icon-s-home"></i>
          <span>主页</span>
        </el-menu-item>
        <el-menu-item index="assistant">
          <i class="el-icon-chat-dot-round"></i>
          <span>智慧助手</span>
        </el-menu-item>
        <el-menu-item index="forum">
          <i class="el-icon-chat-line-round"></i>
          <span>论坛</span>
        </el-menu-item>
        <!-- 新增：慢性病信息入口 -->
        <el-menu-item index="chronic-disease">
          <i class="el-icon-s-order"></i>
          <span>慢性病信息</span>
        </el-menu-item>
      </el-menu>
    </el-aside>

    <!-- 主内容区 -->
    <el-container class="main-content-area">
      <!-- 顶部导航栏 -->
      <el-header class="header">
        <h2 v-if="activeView === 'dashboard'" class="main-title">欢迎来到健康生活助手  为您的健康保驾护航</h2>
        <h2 v-else class="main-title">{{ getViewTitle }}</h2>
      </el-header>

      <!-- 内容显示区域 -->
      <el-main class="content-main">
        <!-- 主页内容 (健康卡片) -->
        <div v-if="activeView === 'dashboard'" class="dashboard-content">
          <el-row :gutter="20">
            <el-col :span="6" v-for="(card, index) in healthCards" :key="index">
              <el-card class="health-card" :body-style="{ padding: '0px' }" :style="{ background: `linear-gradient(to right bottom, ${card.colorStart}, ${card.colorEnd})` }" @click.native="handleCardClick(card)">
                <div class="card-content">
                  <div class="title-row">
                    <i :class="['el-icon-' + card.icon, 'card-icon']" :style="{ color: card.iconColor || '#fff' }"></i>
                    <div class="card-info">
                      <h3 :style="{ color: card.textColor || '#fff' }">{{ card.title }}</h3>
                    </div>
                  </div>
                  <p :style="{ color: card.textColor || '#fff' }">{{ card.description }}</p>
                </div>
              </el-card>
            </el-col>
          </el-row>

          <!-- 日历组件 -->
          <el-row :gutter="20" class="calendar-row">
            <!-- 健康常识卡片 -->
            <el-col :span="16">
              <el-card class="health-tip-card" v-loading="tipLoading">
                <div class="tip-header">
                  <h3>健康小贴士</h3>
                  <el-button type="text" icon="el-icon-refresh" @click="refreshTip">换一个</el-button>
                </div>
                <div class="tip-content" v-if="healthyTip">
                  <div class="tip-icon"><i class="el-icon-star-on"></i></div>
                  <h4>{{ healthyTip.title }}</h4>
                  <p>{{ healthyTip.content }}</p>
                </div>
                <div class="tip-empty" v-else>
                  <i class="el-icon-info-circle"></i>
                  <p>暂无健康常识</p>
                </div>
              </el-card>
            </el-col>
            <el-col :span="8">
              <el-card class="calendar-card">
                <div class="calendar-header">
                  <h3>健康日历</h3>
                  <div class="calendar-header-actions">
                    <p>记录您的健康生活每一天</p>
                    <el-button type="text" icon="el-icon-refresh" @click="loadUserPlans" :loading="isLoadingPlans" class="refresh-btn"></el-button>
                  </div>
                </div>
                <el-calendar v-model="currentDate" v-loading="isLoadingPlans">
                  <template slot="dateCell" slot-scope="{date, data}">
                    <div v-if="isCurrentMonth(date)" class="calendar-cell" 
                         :class="{ 
                           'is-today': isToday(date), 
                           'has-note': hasNote(date),
                           'plan-fitness': hasNoteWithType(date, 'fitness'),
                           'plan-diet': hasNoteWithType(date, 'diet'),
                           'plan-sleep': hasNoteWithType(date, 'sleep'),
                           'plan-health': hasNoteWithType(date, 'health'),
                           'plan-other': hasNoteWithType(date, 'other')
                         }"
                         @click="showNoteDialog(date)">
                      <p>{{ data.day.split('-').slice(2).join('') }}</p>
                      <div class="calendar-dots" v-if="hasNote(date)">
                        <span class="dot" v-for="(event, index) in getEvents(date)" :key="index"
                              :style="{ backgroundColor: event.color }"></span>
                      </div>
                      <i v-if="hasNote(date)" class="el-icon-notebook-2 note-icon"></i>
                    </div>
                    <div v-else class="empty-cell"></div>
                  </template>
                </el-calendar>
                <!-- 添加图例 -->
                <div class="calendar-legend">
                  <div class="legend-item">
                    <span class="legend-color" style="background-color: #67C23A;"></span>
                    <span class="legend-text">健身锻炼</span>
                  </div>
                  <div class="legend-item">
                    <span class="legend-color" style="background-color: #409EFF;"></span>
                    <span class="legend-text">饮食记录</span>
                  </div>
                  <div class="legend-item">
                    <span class="legend-color" style="background-color: #E6A23C;"></span>
                    <span class="legend-text">睡眠记录</span>
                  </div>
                  <div class="legend-item">
                    <span class="legend-color" style="background-color: #F56C6C;"></span>
                    <span class="legend-text">健康检查</span>
                  </div>
                  <div class="legend-item">
                    <span class="legend-color" style="background-color: #909399;"></span>
                    <span class="legend-text">其他记录</span>
                  </div>
                </div>
              </el-card>
            </el-col>
          </el-row>
        </div>

        <!-- 智慧助手内容 -->
        <div v-if="activeView === 'assistant'" class="assistant-content">
          <!-- 聊天消息区域 -->
          <div class="chat-messages-container" ref="chatBox">
            <div v-if="messages.length === 0" class="chat-empty-state">
              <p>有什么我可以帮您的吗？</p>
            </div>
            
            <div v-for="(message, index) in messages" 
                 :key="index" 
                 class="chat-message"
                 :class="{ 'user-message': message.isUser }">
              <div v-if="message.isUser">{{ message.text }}</div>
              <div v-else class="assistant-message" v-html="renderMarkdown(message.text)"></div>
              <div v-if="message.showTable && message.table && message.table.length > 0" 
                   class="table-container">
                <table class="data-table" :style="tableStyle">
                  <thead>
                    <tr>
                      <th v-for="(header, headerIndex) in message.table[0]" 
                          :key="headerIndex">
                        {{ header }}
                      </th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr v-for="(row, rowIndex) in message.table.slice(1)" 
                        :key="rowIndex">
                      <td v-for="(cell, cellIndex) in row" 
                          :key="cellIndex">
                        {{ cell }}
                      </td>
                    </tr>
                  </tbody>
                </table>
              </div>
            </div>
            
            <!-- 加载中的动态提示 -->
            <div v-if="isLoading" class="chat-message loading-message">
              <div class="typing-indicator">
                <span></span>
                <span></span>
                <span></span>
              </div>
              <div class="loading-text">正在思考中...</div>
            </div>
          </div>

          <!-- 输入框 -->
          <div class="chat-input-container">
            <div class="chat-input-wrapper">
              <el-input
                type="textarea"
                v-model="query"
                :rows="1"
                autosize
                placeholder="询问任何健康问题..."
                class="custom-textarea"
                @keyup.enter.native.exact="handleEnterKey"
                :disabled="isStreaming"
              ></el-input>
              <el-button 
                type="primary" 
                circle
                class="send-button"
                @click="sendMessage"
                :disabled="isStreaming"
              >
                <i class="el-icon-s-promotion"></i>
              </el-button>
            </div>
          </div>
        </div>

        <!-- 论坛内容 -->
        <div v-if="activeView === 'forum'" class="forum-content">
          <div class="forum-btn-row">
            <el-button type="primary" @click="$router.push('/forum/create')" style="margin-bottom: 16px;">发帖</el-button>
            <el-button @click="fetchPosts" style="margin-bottom: 16px;">刷新帖子列表</el-button>
          </div>
          <div class="forum-table-wrapper">
            <el-table
              :data="pagedPosts"
              style="width: 100%;"
              v-loading="loadingPosts"
              empty-text="暂无帖子">
              <el-table-column prop="title" label="标题" min-width="200">
                <template slot-scope="scope">
                  <el-link @click="$router.push(`/forum/post/${scope.row.id}`)">{{ scope.row.title }}</el-link>
                </template>
              </el-table-column>
              <el-table-column prop="userId" label="作者ID" width="100"/>
              <el-table-column prop="createdAt" label="发布时间" width="180">
                <template slot-scope="scope">
                  {{ formatDate(scope.row.createdAt) }}
                </template>
              </el-table-column>
              <el-table-column prop="views" label="浏览量" width="100"/>
              <el-table-column prop="likes" label="点赞" width="80"/>
            </el-table>
            <div class="forum-pagination">
              <el-pagination
                background
                layout="prev, pager, next"
                :current-page="currentPage"
                :page-size="pageSize"
                :total="totalPosts"
                @current-change="handlePageChange"
              />
            </div>
          </div>
        </div>
        
        <!-- 慢性病信息总览内容 -->
        <div v-if="activeView === 'chronic-disease'" class="chronic-disease-content">
          <el-card>
            <div style="display:flex;justify-content:space-between;align-items:center;">
              <span style="font-size:20px;font-weight:bold;">慢性病信息总览</span>
              <el-button type="primary" @click="$router.push('/chronic-disease/create')">添加</el-button>
            </div>
            <div class="chronic-disease-table-wrapper">
              <el-table :data="diseaseList" style="margin-top:20px;" empty-text="暂无慢性病记录">
                <el-table-column prop="diseaseName" label="疾病名称"/>
                <el-table-column prop="diagnosisDate" label="确诊日期" :formatter="formatDiseaseDate"/>
                <el-table-column prop="medications" label="用药情况"/>
                <el-table-column prop="managementPlan" label="管理方案"/>
                <el-table-column prop="lastCheckupDate" label="上次复查" :formatter="formatDiseaseDate"/>
                <el-table-column prop="nextCheckupDate" label="下次复查" :formatter="formatDiseaseDate"/>
                <el-table-column prop="notes" label="备注"/>
                <el-table-column label="操作" width="120">
                  <template slot-scope="scope">
                    <el-button type="danger" size="mini" @click="deleteDisease(scope.row.id)">删除</el-button>
                  </template>
                </el-table-column>
              </el-table>
            </div>
          </el-card>
        </div>
      </el-main>
    </el-container>

    <!-- 记录笔记的对话框 -->
    <el-dialog
      :title="hasExistingNote ? '编辑记录' : '添加记录'"
      :visible.sync="noteDialogVisible"
      width="30%"
      :before-close="handleNoteDialogClose"
      class="note-dialog">
      <!-- 添加自定义关闭按钮，替代原来的× -->
      <div class="custom-close-btn" @click="handleCloseBtn">
        <i class="el-icon-close"></i>
      </div>
      <div class="note-dialog-content">
        <p class="selected-date">{{ formatDateChinese(currentDate) }}</p>
        <!-- 添加计划类型选择 -->
        <div class="plan-type-select">
          <el-select v-model="currentPlanType" placeholder="请选择计划类型" style="width: 100%; margin-bottom: 15px;">
            <el-option label="健身锻炼" value="fitness"></el-option>
            <el-option label="饮食记录" value="diet"></el-option>
            <el-option label="睡眠记录" value="sleep"></el-option>
            <el-option label="健康检查" value="health"></el-option>
            <el-option label="其他记录" value="other"></el-option>
          </el-select>
        </div>
        <el-input
          type="textarea"
          :rows="4"
          placeholder="请输入今天的健康记录..."
          v-model="currentNote"
          class="note-textarea">
        </el-input>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button type="danger" v-if="hasExistingNote" @click="deleteNote">删除记录</el-button>
        <el-button @click="noteDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="saveNote">保 存</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import axios from 'axios';
import { marked } from 'marked';

export default {
  name: 'HomeView',
  data() {
    return {
      username: '',
      userAvatar: 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png',
      activeView: 'dashboard',
      query: "",
      messages: [],
      isLoading: false,
      isStreaming: false,
      streamSpeed: 15,
      healthCards: [
        {
          title: '睡眠记录',
          description: '记录您的睡眠质量，提供睡眠分析',
          icon: 'moon',
          colorStart: '#87CEFA',
          colorEnd: '#4682B4',
          iconColor: '#fff',
          textColor: '#fff',
          route: '/sleep'
        },
        {
          title: '运动记录',
          description: '追踪您的运动数据，记录运动轨迹',
          icon: 's-data',
          colorStart: '#90EE90',
          colorEnd: '#32CD32',
          iconColor: '#fff',
          textColor: '#fff',
          route: '/exercise'
        },
        {
          title: '健身计划',
          description: '制定个性化健身计划，科学锻炼',
          icon: 'date',
          colorStart: '#FFD700',
          colorEnd: '#FFA500',
          iconColor: '#fff',
          textColor: '#fff',
          route: '/fitness'
        },
        {
          title: '饮食分析',
          description: '分析您的饮食习惯，提供健康建议',
          icon: 'food',
          colorStart: '#FFA07A',
          colorEnd: '#FA8072',
          iconColor: '#fff',
          textColor: '#fff',
          route: '/diet'
        }
      ],
      currentDate: new Date(),
      noteDialogVisible: false,
      currentNote: '',
      currentPlanType: '',
      notes: {},
      // 计划类型对应的颜色
      planTypeColors: {
        'fitness': '#67C23A',  // 绿色
        'diet': '#409EFF',     // 蓝色
        'sleep': '#E6A23C',    // 黄色
        'health': '#F56C6C',   // 红色
        'other': '#909399'     // 灰色
      },
      // 移除静态events数据
      healthyTip: null,
      tipLoading: false,
      isLoadingPlans: false, // 添加加载计划状态
      forumPosts: [],
      loadingPosts: false,
      currentPage: 1,
      pageSize: 10,
      totalPosts: 0,
      diseaseList: [],
    }
  },
  computed: {
    getViewTitle() {
      switch(this.activeView) {
        case 'assistant':
          return '智慧助手';
        case 'forum':
          return '论坛';
        default:
          return '';
      }
    },
    tableStyle() {
      const columnCount = this.tableHeaders ? this.tableHeaders.length : 0;
      const columnWidth = 200;
      
      if (columnCount <= 4) {
        return {
          width: '100%'
        };
      } else {
        return {
          width: `${columnCount * columnWidth}px`
        };
      }
    },
    hasExistingNote() {
      return !!this.notes[this.formatDate(this.currentDate)];
    },
    pagedPosts() {
      const start = (this.currentPage - 1) * this.pageSize;
      return this.forumPosts.slice(start, start + this.pageSize);
    }
  },
  methods: {
    handleMenuSelect(index) {
      this.activeView = index;
      let tab = index;
      this.$router.replace({ path: '/home', query: { tab } });
    },
    handleLogout() {
      // 调用后端登出接口
      this.axios.post('/api/user/logout')
        .then(response => {
          if (response.data && response.data.message === "退出成功") {
            // 清除本地存储的用户信息
            sessionStorage.removeItem('userInfo');
            
            // 清空组件中的用户信息
            this.username = '';
            this.userAvatar = '';
            
            // 显示成功消息
            this.$message({
              message: '退出成功',
              type: 'success'
            });
            
            // 跳转到登录页
            this.$router.push('/');
          } else {
            throw new Error('退出失败');
          }
        })
        .catch(error => {
          console.error('退出失败:', error);
          this.$message({
            message: '退出失败，请重试',
            type: 'error'
          });
        });
    },
    async sendMessage() {
      if (!this.query.trim() || this.isStreaming) return;

      const userQuery = this.query.trim();
      this.messages.push({ text: userQuery, isUser: true });
      this.query = "";
      
      await this.$nextTick();
      this.scrollToBottom();

      this.isLoading = true;
      this.isStreaming = true;
      
      const responseMessage = {
        text: "",
        isUser: false,
        streaming: true
      };
      this.messages.push(responseMessage);

      try {
        // 调用新的后端API
        const response = await this.axios.post("/api/assist/ask", {
          question: userQuery
        });
        
        if (response.data && response.data.answer) {
          // 使用流式输出显示回答
          await this.streamText(responseMessage, response.data.answer);
        } else {
          throw new Error('返回数据格式不正确');
        }
      } catch (error) {
        console.error("请求错误:", error);
        await this.streamText(responseMessage, "抱歉，请求失败，请稍后重试。");
      } finally {
        this.isLoading = false;
        this.isStreaming = false;
        responseMessage.streaming = false;
        await this.$nextTick();
        this.scrollToBottom();
      }
    },
    async streamText(message, text) {
      let currentIndex = 0;
      
      const stream = async () => {
        if (currentIndex < text.length) {
          message.text += text[currentIndex];
          currentIndex++;
          
          await this.$nextTick();
          this.scrollToBottom();
          
          return new Promise(resolve => {
            setTimeout(() => resolve(stream()), this.streamSpeed);
          });
        }
      };

      await stream();
    },
    scrollToBottom() {
      this.$nextTick(() => {
        const chatBox = this.$refs.chatBox;
        if (chatBox) {
          chatBox.scrollTop = chatBox.scrollHeight;
        }
      });
    },
    adjustHeight() {
      const textarea = this.$refs.textarea;
      const wrapper = this.$refs.inputWrapper;
      
      if (textarea && wrapper) {
        textarea.style.height = 'auto';
        const scrollHeight = textarea.scrollHeight;
        const newHeight = Math.min(Math.max(scrollHeight, 60), 200);
        textarea.style.height = `${newHeight}px`;
        wrapper.style.height = `${newHeight + 20}px`;
      }
    },
    isToday(date) {
      const today = new Date();
      return date.getDate() === today.getDate() &&
             date.getMonth() === today.getMonth() &&
             date.getFullYear() === today.getFullYear();
    },
    hasEvents(date) {
      const dateStr = this.formatDate(date);
      return this.notes[dateStr] && this.notes[dateStr].planType;
    },
    getEvents(date) {
      const dateStr = this.formatDate(date);
      if (this.notes[dateStr] && this.notes[dateStr].planType) {
        const planType = this.notes[dateStr].planType;
        return [{
          color: this.planTypeColors[planType] || this.planTypeColors.other
        }];
      }
      return [];
    },
    formatDate(date) {
      // 如果是字符串，自动转为Date对象
      if (typeof date === 'string') {
        date = new Date(date);
      }
      if (!(date instanceof Date) || isNaN(date.getTime())) {
        return '';
      }
      const year = date.getFullYear();
      const month = String(date.getMonth() + 1).padStart(2, '0');
      const day = String(date.getDate()).padStart(2, '0');
      
      // 只返回日期部分，不包含时间，以匹配后端的日期格式
      return `${year}-${month}-${day}`;
      const hour = String(date.getHours()).padStart(2, '0');
      const minute = String(date.getMinutes()).padStart(2, '0');
      return `${year}-${month}-${day} ${hour}:${minute}`;
    },
    showNoteDialog(date) {
      this.currentDate = date;
      const dateStr = this.formatDate(date);
      
      if (this.notes[dateStr]) {
        this.currentNote = this.notes[dateStr].content || '';
        this.currentPlanType = this.notes[dateStr].planType || '';
      } else {
        this.currentNote = '';
        this.currentPlanType = '';
      }
      
      this.noteDialogVisible = true;
    },
    handleNoteDialogClose(done) {
      // 有修改但未保存时显示确认提示
      const dateStr = this.formatDate(this.currentDate);
      const oldNote = this.notes[dateStr] ? this.notes[dateStr].content || '' : '';
      
      if (this.currentNote !== oldNote && this.currentNote.trim() !== '') {
        this.$confirm('确认关闭？未保存的内容将会丢失')
          .then(_ => {
            this.currentNote = '';
            this.currentPlanType = '';
            if (done) done();
          })
          .catch(_ => {});
      } else {
        // 无修改或内容为空直接关闭
        this.currentNote = '';
        this.currentPlanType = '';
        if (done) done();
      }
    },
    async saveNote() {
      try {
        const dateStr = this.formatDate(this.currentDate);
        
        if (this.currentNote.trim()) {
          // 如果没有选择计划类型，默认为"其他"
          const planType = this.currentPlanType || 'other';
          
          // 准备请求数据
          const planData = {
            planType: planType,
            content: this.currentNote.trim(),
            planTime: dateStr
          };
          
          // 添加/覆盖计划 - 后端会自动处理同一天的覆盖逻辑
          const response = await this.axios.post('/api/user/plan/add', planData);
          const success = response.data.success;
          const message = response.data.message;
          
          // 如果后端返回了id，保存它
          if (response.data.data && response.data.data.id) {
            planData.id = response.data.data.id;
          }
          
          if (success) {
            // 更新本地数据
            this.notes[dateStr] = {
              content: this.currentNote.trim(),
              planType: planType,
              planTime: dateStr,
              id: planData.id // 保存可能从后端返回的id
            };
            
            this.$message({
              type: 'success',
              message: message || '记录保存成功'
            });
          } else {
            this.$message({
              type: 'error',
              message: message || '保存失败，请重试'
            });
          }
        } else {
          // 如果内容为空，且有当前日期的记录，则删除计划
          if (this.notes[dateStr]) {
            await this.deleteNote();
          } else {
            this.$message({
              type: 'warning',
              message: '记录已清空'
            });
          }
        }
        
        this.noteDialogVisible = false;
      } catch (error) {
        console.error('保存计划失败:', error);
        this.$message({
          type: 'error',
          message: '保存失败，请检查网络连接'
        });
      }
    },
    async deleteNote() {
      try {
        const dateStr = this.formatDate(this.currentDate);
        if (!this.notes[dateStr]) {
          this.noteDialogVisible = false;
          this.$message({
            type: 'success',
            message: '记录已清空'
          });
          return;
        }
        
        // 确认删除
        await this.$confirm('确认删除这条记录？此操作不可恢复', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        });
        
        // 调用删除API，传递planTime参数
        const response = await this.axios.delete(`/api/user/plan/delete?planTime=${dateStr}`);
        
        if (response.data.success) {
          delete this.notes[dateStr];
          
          this.$message({
            type: 'success',
            message: '删除成功'
          });
        } else {
          this.$message({
            type: 'error',
            message: response.data.message || '删除失败'
          });
        }
        
        this.noteDialogVisible = false;
      } catch (error) {
        if (error === 'cancel') {
          // 用户取消删除，不做处理
          return;
        }
        console.error('删除计划失败:', error);
        this.$message({
          type: 'error',
          message: '删除失败，请检查网络连接'
        });
      }
    },
    formatDateChinese(date) {
      const year = date.getFullYear();
      const month = date.getMonth() + 1;
      const day = date.getDate();
      const weekDay = ['日', '一', '二', '三', '四', '五', '六'][date.getDay()];
      return `${year}年${month}月${day}日 星期${weekDay}`;
    },
    hasNote(date) {
      const dateStr = this.formatDate(date);
      return !!this.notes[dateStr];
    },
    isCurrentMonth(date) {
      const currentMonth = this.currentDate.getMonth();
      const currentYear = this.currentDate.getFullYear();
      return date.getMonth() === currentMonth && date.getFullYear() === currentYear;
    },
    // 添加自定义关闭按钮处理方法
    handleCloseBtn() {
      this.handleNoteDialogClose(() => {
        this.noteDialogVisible = false;
      });
    },
    handleCardClick(card) {
      if (card.route) {
        this.$router.push(card.route);
      }
    },
    // 获取健康常识
    async fetchHealthyTip() {
      this.tipLoading = true;
      try {
        // 随机生成1-38之间的整数
        const randomId = Math.floor(Math.random() * 38) + 1;
        // 调用接口获取健康常识
        const response = await this.axios.get(`/api/healthTips/${randomId}`);
        
        // 验证返回的数据
        if (response.data && response.data.title && response.data.content) {
          this.healthyTip = response.data;
        } else {
          throw new Error('返回的健康常识数据格式不正确');
        }
      } catch (error) {
        console.error("获取健康常识失败:", error);
        this.$message.error("获取健康常识失败，请稍后重试");
        this.healthyTip = null;
      } finally {
        this.tipLoading = false;
      }
    },
    // 刷新健康常识
    refreshTip() {
      this.fetchHealthyTip();
    },
    // 处理回车键
    handleEnterKey(e) {
      if (e.ctrlKey || e.shiftKey || e.altKey) return; // 如果按下了修饰键，不发送
      if (!this.query.trim() || this.isStreaming) return; // 如果输入为空或正在流式输出，不发送
      
      e.preventDefault(); // 阻止默认行为
      this.sendMessage(); // 发送消息
    },
    // 添加markdown渲染方法
    renderMarkdown(text) {
      if (!text) return '';
      
      try {
        // 1. 清理文本 - 移除多余空白并处理特殊字符
        let processedText = text
          // 将连续的多个换行符替换为一个换行符（特别关注：确保所有\n\n替换为\n，包括列表间的换行）
          .replace(/\n{2,}/g, '\n')
          // 移除行首多余空格
          .replace(/^\s+/gm, '')
          // 移除行尾多余空格
          .replace(/\s+$/gm, '')
          // 处理数字序号格式（如 1. 1. 科学健康知识）- 缩小编号间距
          .replace(/(\d+)\.\s+(\d+)\.\s+/g, '<span class="number-prefix">$1.$2.</span> ')
          // 处理单数字序号格式（如 1. 科学健康知识）
          .replace(/^(\d+)\.\s+/gm, '<span class="number-prefix">$1.</span> ')
          // 处理下划线强调文本
          .replace(/_(.*?)_/g, '<em>$1</em>')
          // 处理星号强调文本
          .replace(/\*(.*?)\*/g, '<em>$1</em>')
          // 处理双星号加粗文本
          .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
          // 处理双下划线加粗文本
          .replace(/__(.*?)__/g, '<strong>$1</strong>');
        
        // 2. 预处理连续的列表项，确保不同类型列表之间无空行
        // 查找有序列表项和无序列表项交替的模式并紧密连接它们
        processedText = processedText
          // 检测无序列表项后跟有序列表项的模式，中间可能有空白行
          .replace(/^([*\-•◆]\s+.*?)$\s*^(\d+\.\s+.*?)$/gm, '$1\n$2')
          // 检测有序列表项后跟无序列表项的模式，中间可能有空白行
          .replace(/^(\d+\.\s+.*?)$\s*^([*\-•◆]\s+.*?)$/gm, '$1\n$2');
          
        // 处理列表项
        processedText = processedText
          // 处理无序列表 (处理多种可能的列表符号: •, -, *, 等)
          .replace(/^[\s]*[•\-\*◆][\s]+(.*?)$/gm, '<li>$1</li>')
          // 处理有序列表
          .replace(/^[\s]*(\d+)\.[\s]+(.*?)$/gm, '<li>$1. $2</li>')
          // 确保列表项之间没有多余的空行，只有一个换行符
          .replace(/<\/li>\n+<li>/g, '</li>\n<li>');

        // 3. 将连续的<li>标签包装在<ul>或<ol>中
        let inList = false;
        let listType = '';
        let currentListIsOrdered = false;
        let lastLineWasList = false;
        const lines = processedText.split('\n');
        let result = '';
        
        for (let i = 0; i < lines.length; i++) {
          let line = lines[i].trim();
          if (!line) continue; // 跳过空行
          
          const isListItem = line.match(/<li>/);
          const isOrderedList = isListItem && line.match(/<li>\d+\./);
          
          if (isListItem) {
            // 当前行是列表项
            if (!inList) {
              // 开始新列表，确保列表前没有多余换行
              // 完全删除之前添加的换行符，使列表更加紧凑
              
              if (isOrderedList) {
                result += '<ol class="markdown-list">';
                listType = 'ol';
                currentListIsOrdered = true;
              } else {
                result += '<ul class="markdown-list">';
                listType = 'ul';
                currentListIsOrdered = false;
              }
              inList = true;
            } else if ((isOrderedList && !currentListIsOrdered) || (!isOrderedList && currentListIsOrdered)) {
              // 列表类型变化 (从有序到无序或从无序到有序)
              // 直接连接不同类型的列表，不添加换行符
              result = result.trimEnd();
              result += `</${listType}><${isOrderedList ? 'ol' : 'ul'} class="markdown-list adjacent-list" style="margin-top:-15px !important;">`;
              
              listType = isOrderedList ? 'ol' : 'ul';
              currentListIsOrdered = isOrderedList;
              inList = true;
            }
            result += line;
            lastLineWasList = true;
          } else {
            // 当前行不是列表项
            if (inList) {
              result = result.trimEnd(); // 删除前一个列表项后的所有空白
              result += `</${listType}>`;
              inList = false;
            }
            
            // 4. 处理标题
            if (line.match(/^#{1,6}\s/)) {
              const level = line.match(/^(#{1,6})\s/)[1].length;
              const content = line.replace(/^#{1,6}\s/, '');
              // 添加紧凑型标题样式
              line = `<h${level} class="markdown-heading compact-heading">${content}</h${level}>`;
            } 
            // 5. 处理普通段落
            else if (line.trim() !== '') {
              // 处理引用块
              if (line.startsWith('>')) {
                line = `<blockquote class="markdown-blockquote">${line.substring(1).trim()}</blockquote>`;
              } else {
                // 为从列表项后的第一个段落添加适当的外边距
                if (lastLineWasList) {
                  line = `<p class="markdown-paragraph" style="margin-top:1px !important">${line}</p>`;
                  lastLineWasList = false;
                } else if (line.includes('<span class="number-prefix">')) {
                  // 数字前缀段落使用紧凑样式
                  line = `<p class="markdown-paragraph compact-paragraph">${line}</p>`;
                } else {
                  line = `<p class="markdown-paragraph">${line}</p>`;
                }
              }
            }
            
            // 添加当前行，确保不会有多余的换行，并删除任何多余的空格
            result += line;
          }
        }
        
        // 如果最后一行是列表项，确保关闭列表标签
        if (inList) {
          result = result.trimEnd(); // 删除前一个列表项后的所有空白
          result += `</${listType}>`;
        }
        
        // 6. 处理表情符号
        result = result
          .replace(/:[\)]/g, '😊')
          .replace(/:\(/g, '😔')
          .replace(/;\)/g, '😉')
          .replace(/:D/g, '😃')
          .replace(/:P/g, '😜')
          .replace(/<3/g, '❤️')
          .replace(/🌱/g, '🌱');
          
        // 7. 清理多余引号
        result = result
          .replace(/"([^"]*?)"/g, '「$1」')
          .replace(/_([^_]*?)_/g, '$1');
          
        // 8. 处理连续的下划线的问题
        result = result.replace(/_{2,}/g, '');
        
        // 9. 处理特殊符号
        result = result
          .replace(/◆/g, '•')
          .replace(/♦/g, '•');
        
        // 10. 最终清理 - 删除所有HTML标签之间的换行符和多余空白
        result = result
          // 删除标签之间的换行符
          .replace(/>\s*\n\s*</g, '><')
          // 删除两个标签之间的多余空白
          .replace(/>\s+</g, '><')
          // 删除列表开始标签和列表项之间的空白
          .replace(/<(ul|ol)[^>]*>\s+<li/g, '<$1><li')
          // 删除列表项和列表结束标签之间的空白
          .replace(/<\/li>\s+<\/(ul|ol)/g, '</li></$1')
          // 清理任何连续的空白字符
          .replace(/\s{2,}/g, ' ');
        
        // 返回处理后的HTML
        return result;
      } catch (error) {
        console.error('文本渲染错误:', error);
        return text;
      }
    },
    // 获取用户名
    async fetchUsername() {
      try {
        const response = await this.axios.get('/api/user/username', {
          withCredentials: true // 确保发送请求时携带Cookie
        });
        
        if (response.data && response.data.success) {
          // 成功获取用户名
          this.username = response.data.username;
        } else {
          // 获取失败但有响应
          console.warn('获取用户名失败:', response.data.message);
          
          // 尝试从sessionStorage获取用户信息作为备选
          const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}');
          if (userInfo.email) {
            // 如果有email，使用email前缀作为用户名
            this.username = userInfo.email.split('@')[0];
          } else {
            // 如果没有任何用户信息，设置默认用户名
            this.username = '用户';
          }
        }
      } catch (error) {
        console.error('获取用户名请求失败:', error);
        
        // 出错时也尝试从sessionStorage获取
        try {
          const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}');
          if (userInfo.email) {
            this.username = userInfo.email.split('@')[0];
          } else {
            this.username = '用户';
          }
        } catch (e) {
          this.username = '用户';
        }
      }
    },
    hasNoteWithType(date, type) {
      const dateStr = this.formatDate(date);
      return this.notes[dateStr] && this.notes[dateStr].planType === type;
    },
    // 添加加载用户计划的方法
    async loadUserPlans() {
      try {
        this.isLoadingPlans = true;
        const response = await this.axios.get('/api/user/plan/list');
        
        if (response.data.success && Array.isArray(response.data.data)) {
          // 清空当前笔记数据
          this.notes = {};
          
          // 将后端返回的计划数据转换为前端使用的格式
          response.data.data.forEach(plan => {
            if (plan.planTime && plan.content) {
              // 处理ISO格式的日期字符串，提取年-月-日部分
              let dateStr;
              if (typeof plan.planTime === 'string' && plan.planTime.includes('T')) {
                // ISO格式日期，如 "2025-05-01T00:00:00.000+00:00"
                dateStr = plan.planTime.split('T')[0]; // 提取 "2025-05-01" 部分
              } else {
                // 已经是YYYY-MM-DD格式
                dateStr = plan.planTime;
              }
              
              this.notes[dateStr] = {
                content: plan.content,
                planType: plan.planType || 'other',
                planTime: dateStr,
                id: plan.id // 保存id，便于后续更新和删除操作
              };
            }
          });
        } else {
          this.$message({
            type: 'warning',
            message: '获取计划数据失败'
          });
        }
      } catch (error) {
        console.error('加载用户计划失败:', error);
        this.$message({
          type: 'error',
          message: '加载计划失败，请检查网络连接'
        });
      } finally {
        this.isLoadingPlans = false;
      }
    },
    async fetchPosts() {
      this.loadingPosts = true;
      try {
        const response = await this.axios.get('/api/forum/posts');
        this.forumPosts = response.data || [];
        this.totalPosts = this.forumPosts.length;
        // 新增：为每个帖子获取点赞数
        await Promise.all(this.forumPosts.map(async (post) => {
          try {
            const res = await this.axios.get(`/api/forum/posts/${post.id}/likes`);
            // 赋值到post.likes
            post.likes = res.data;
          } catch (e) {
            post.likes = 0;
          }
        }));
        // 如果当前页超出最大页，自动跳到最后一页
        const maxPage = Math.max(1, Math.ceil(this.totalPosts / this.pageSize));
        if (this.currentPage > maxPage) {
          this.currentPage = maxPage;
        }
      } catch (error) {
        console.error('获取帖子列表失败:', error);
      } finally {
        this.loadingPosts = false;
      }
    },
    handleViewPost(post) {
      // 实现查看帖子逻辑
      console.log('查看帖子:', post);
    },
    handlePageChange(page) {
      this.currentPage = page;
      // 如果后端支持分页API，这里可以重新请求数据
      // this.fetchPosts(page);
    },
    fetchDiseaseList() {
      this.axios.get('/api/health/chronic-disease/list').then(res => {
        if(res.data.success) {
          this.diseaseList = res.data.data || [];
        } else {
          this.$message.error(res.data.message || '获取失败');
        }
      });
    },
    deleteDisease(id) {
      this.$confirm('确定要删除这条慢性病记录吗？', '提示', {type: 'warning'}).then(() => {
        this.axios.delete(`/api/health/chronic-disease/delete/${id}`).then(res => {
          if(res.data.success) {
            this.$message.success('删除成功');
            this.fetchDiseaseList();
          } else {
            this.$message.error(res.data.message || '删除失败');
          }
        });
      });
    },
    formatDiseaseDate(row, column, cellValue) {
      if (!cellValue) return '';
      const d = new Date(cellValue);
      return isNaN(d.getTime()) ? '' : d.toLocaleDateString();
    },
  },
  watch: {
    messages: {
      handler() {
        this.$nextTick(() => {
          this.scrollToBottom();
        });
      },
      deep: true
    },
    activeView(newVal) {
      if (newVal === 'forum') {
        this.fetchPosts();
      }
      if (newVal === 'chronic-disease') {
        this.fetchDiseaseList();
      }
    },
    '$route'(to) {
      // 新增：路由变化时根据query切换tab
      if (to.query.tab) {
        this.activeView = to.query.tab;
      }
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.adjustHeight();
      this.scrollToBottom();
      this.fetchHealthyTip();
      this.fetchUsername();
      // 加载用户计划
      this.loadUserPlans();
      // 根据路由参数设置初始tab
      // 新增：根据路由参数设置初始tab
      if (this.$route.query.tab) {
        this.activeView = this.$route.query.tab;
      }
      if (this.activeView === 'chronic-disease') {
        this.fetchDiseaseList();
      }
    });
  }
}
</script>

<style scoped>
.home-container {
  display: flex;
  height: 100vh;
}

.sidebar {
  background-color: #304156;
  color: #fff;
  display: flex;
  flex-direction: column;
}

.sidebar-user-info {
  height: 60px;
  display: flex;
  align-items: center;
  padding: 0 20px;
  box-sizing: border-box;
  background-color: #263445;
  border-bottom: 1px solid #4d5a6a;
  flex-shrink: 0;
}

.el-menu-vertical {
  border-right: none;
  flex-grow: 1;
}

.el-menu-item {
  height: 50px;
  line-height: 50px;
  padding-left: 20px !important;
}

.el-menu-item i {
  margin-right: 10px;
  width: 24px;
  text-align: center;
  color: #bfcbd9;
}

.el-menu-item span {
   font-size: 21px;
}

.el-menu-item:hover {
  background-color: #263445 !important;
}

.el-menu-item.is-active {
  background-color: #409EFF !important;
  color: #fff !important;
}

.el-menu-item.is-active i {
  color: #fff;
}

.user-avatar {
  display: flex;
  align-items: center;
  cursor: pointer;
}

.username {
  margin-left: 10px;
  font-size: 21px;
  color: #bfcbd9;
}

.main-content-area {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

.header {
  background-color: #fff;
  border-bottom: 1px solid #e6e6e6;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px 20px;
  flex-shrink: 0;
  min-height: 100px;
}

.main-title {
  text-align: center;
  font-size: 48px;
  background: linear-gradient(to right, #409EFF, #67c23a);
  -webkit-background-clip: text;
  color: transparent;
  font-weight: bold;
  letter-spacing: 3px;
  text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
  font-family: cursive, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
  transition: all 0.3s ease;
}

.content-main {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
  background-color: #f5f7fa;
  min-height: 0;
}

.health-card {
  margin-bottom: 20px;
  border-radius: 15px;
  transition: all 0.3s;
  border: none;
  height: 200px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  overflow: hidden;
  position: relative;
}

.health-card:hover {
  transform: translateY(-8px);
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
}

.card-content {
  padding: 20px;
  display: flex;
  flex-direction: column;
  text-align: left;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
}

/* 标题行：图标和标题水平排列 */
.title-row {
  display: flex;
  align-items: center;
  margin-bottom: 15px;
}

.card-icon {
  font-size: 42px;
  flex-shrink: 0;
  margin-right: 15px;
}

.card-info {
  display: flex;
  flex-direction: column;
  width: 100%;
  overflow: hidden;
}

.card-info h3 {
  margin: 0;
  font-size: 24px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.card-info p {
  margin: 0;
  font-size: 16px;
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  word-break: break-word;
}

.assistant-content h1,
.forum-content h1 {
  color: #333;
  margin-bottom: 15px;
}

.assistant-content p,
.forum-content p {
  color: #666;
  font-size: 18px;
}

.assistant-content {
  height: 100%;
  display: flex;
  flex-direction: column;
  background-color: #f9fafc;
  padding: 20px;
  position: relative;
  overflow: hidden;
}

.welcome-header {
  text-align: center;
  padding: 24px 0;
  margin-bottom: 20px;
}

.welcome-title {
  font-size: 32px;
  font-weight: 600;
  margin: 0;
  background: linear-gradient(90deg, #4f8bff, #2d62ff);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  letter-spacing: 1px;
}

.chat-messages-container {
  flex: 1;
  overflow-y: auto;
  padding: 10px;
  display: flex;
  flex-direction: column;
  margin-bottom: 120px;
  height: calc(100vh - 250px);
}

.chat-empty-state {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  color: #333;
}

.chat-empty-state p {
  font-size: 32px;
  margin: 0;
  font-weight: 400;
}

.chat-message {
  display: inline-block;
  max-width: 80%;
  min-width: 50px;
  padding: 6px 10px;
  margin-bottom: 4px;
  border-radius: 8px;
  background-color: #fff;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
  text-align: left;
  word-wrap: break-word;
  word-break: break-word;
  align-self: flex-start;
  font-size: 21px;
  line-height: 1.4;
}

.chat-message div {
  text-align: left;
  white-space: pre-wrap;
  font-size: 19px;
  line-height: 1.3;
}

/* 优化用户消息样式 */
.user-message {
  align-self: flex-end;
  background-color: #ecf5ff;
  color: #409EFF;
  max-width: 60%;
  padding: 4px 10px;
  margin-bottom: 3px;
}

/* 自定义Markdown渲染样式 */
.chat-message .markdown-list {
  padding-left: 18px !important;
  margin: 1px 0 !important;
  list-style-position: outside !important;
}

.chat-message .markdown-list li {
  display: list-item !important;
  margin-bottom: 0 !important;
  line-height: 1.3 !important;
  padding-left: 4px !important;
}

.chat-message ul.markdown-list {
  list-style-type: disc !important;
}

.chat-message ol.markdown-list {
  list-style-type: decimal !important;
}

.chat-message .markdown-paragraph {
  margin: 2px 0 !important;
  line-height: 1.4 !important;
}

/* 紧凑型段落样式 */
.chat-message .compact-paragraph {
  margin: 0 !important;
  line-height: 1.3 !important;
}

/* 数字前缀样式 */
.chat-message .number-prefix {
  font-weight: 500;
  margin-right: 2px;
  white-space: nowrap;
}

.chat-message .markdown-heading {
  margin: 4px 0 2px 0 !important;
  font-weight: bold !important;
  line-height: 1.3 !important;
}

/* 紧凑型标题 */
.chat-message .compact-heading {
  margin: 1px 0 1px 0 !important;
  line-height: 1.2 !important;
}

.chat-message h1.markdown-heading {
  font-size: 22px !important;
}

.chat-message h2.markdown-heading {
  font-size: 21px !important;
}

.chat-message h3.markdown-heading {
  font-size: 20px !important;
}

.chat-message em, .chat-message i {
  font-style: italic !important;
}

.chat-message strong, .chat-message b {
  font-weight: bold !important;
}

.chat-message .markdown-blockquote {
  border-left: 3px solid #ddd !important;
  padding-left: 8px !important;
  margin: 3px 0 !important;
  color: #555 !important;
  font-style: italic !important;
}

.loading-message {
  background-color: #f5f7fa;
  align-self: flex-start;
}

.chat-input-container {
  position: fixed;
  bottom: 30px;
  left: 50%;
  transform: translateX(-50%);
  width: 1000px;
  max-width: 95%;
  padding: 0;
  z-index: 1000;
}

.chat-input-wrapper {
  position: relative;
  background: white;
  border-radius: 25px;
  padding: 20px 25px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
  display: flex;
  align-items: flex-start;
  border: 1px solid rgba(0, 0, 0, 0.03);
}

.custom-textarea {
  margin-right: 65px;
  width: 100%;
}

.custom-textarea :deep(.el-textarea__inner) {
  border: none;
  padding: 12px 0;
  font-size: 24px;
  resize: none;
  box-shadow: none;
  background-color: transparent;
  color: #333;
  max-height: calc(24px * 1.5 * 7 + 24px);
  overflow-y: auto;
}

.custom-textarea :deep(.el-textarea__inner):focus {
  box-shadow: none;
}

.custom-textarea :deep(.el-textarea__inner)::placeholder {
  color: #909399;
}

/* 自定义滚动条样式 */
.custom-textarea :deep(.el-textarea__inner)::-webkit-scrollbar {
  width: 6px;
}

.custom-textarea :deep(.el-textarea__inner)::-webkit-scrollbar-thumb {
  background-color: #909399;
  border-radius: 3px;
}

.custom-textarea :deep(.el-textarea__inner)::-webkit-scrollbar-track {
  background-color: #f5f7fa;
  border-radius: 3px;
}

.send-button {
  position: absolute;
  right: 15px;
  bottom: 15px;
  width: 60px;
  height: 60px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #409EFF;
  transition: all 0.3s ease;
}

.send-button i {
  font-size: 28px;
  margin: 0;
}

.send-button:disabled {
  background-color: #a0cfff;
  cursor: not-allowed;
  transform: none;
}

.table-container {
  margin-top: 16px;
  overflow-x: auto;
}

.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 21px;
}

.data-table th,
.data-table td {
  border: 1px solid #dfe2e5;
  padding: 8px 12px;
}

.data-table th {
  background-color: #F5F7FA;
  color: #909399;
  font-weight: 500;
}

.typing-indicator {
  display: flex;
  gap: 4px;
  margin-bottom: 8px;
}

.typing-indicator span {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: #909399;
  animation: typing 1s infinite ease-in-out;
}

@keyframes typing {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-4px); }
}

.loading-text {
  color: #909399;
  font-size: 21px;
}

/* 自定义主滚动条样式 */
.chat-messages-container::-webkit-scrollbar {
  width: 6px;
}

.chat-messages-container::-webkit-scrollbar-thumb {
  background-color: #909399;
  border-radius: 3px;
}

.chat-messages-container::-webkit-scrollbar-track {
  background-color: #f5f7fa;
  border-radius: 3px;
}

.calendar-row {
  margin-top: 10px;
  display: flex;
  padding: 0 20px;
  margin-bottom: 40px;
}

.calendar-card {
  border-radius: 15px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
  transition: all 0.3s;
  transform: rotate(-2deg);
  background: linear-gradient(135deg, #fff 0%, #f8f9fa 100%);
  border: 1px solid rgba(255, 255, 255, 0.8);
  backdrop-filter: blur(10px);
  position: relative;
  z-index: 1;
  padding-bottom: 0;
}

.calendar-card:hover {
  transform: rotate(0deg) translateY(-5px);
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.12);
}

.calendar-header {
  padding: 10px;
  text-align: center;
  border-bottom: 1px solid rgba(235, 238, 245, 0.6);
  background: linear-gradient(135deg, #409EFF 0%, #67C23A 100%);
  border-radius: 15px 15px 0 0;
  position: relative;
  overflow: hidden;
}

.calendar-header-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.calendar-header p {
  margin: 3px 0 0;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.9);
  text-shadow: 0 1px 2px rgba(0,0,0,0.1);
}

.refresh-btn {
  color: #fff;
  font-size: 16px;
  padding: 0;
  margin: 0;
}

.refresh-btn:hover {
  color: #f0f0f0;
  transform: rotate(180deg);
  transition: transform 0.5s;
}

.calendar-header::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(45deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0) 100%);
  pointer-events: none;
}

.calendar-header h3 {
  margin: 0;
  font-size: 16px;
  color: #fff;
  font-weight: 600;
  text-shadow: 0 1px 2px rgba(0,0,0,0.1);
}

.calendar-cell {
  height: 100%;
  padding: 2px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  transition: all 0.3s;
  cursor: pointer;
  position: relative;
  background: rgba(255, 255, 255, 0.5);
}

.calendar-cell:hover {
  background-color: rgba(64, 158, 255, 0.1);
  transform: scale(1.02);
}

.calendar-cell p {
  margin: 0;
  font-size: 12px;
  color: #606266;
  font-weight: 500;
}

.calendar-cell.is-today {
  background-color: rgba(64, 158, 255, 0.15);
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2);
}

.calendar-cell.is-today p {
  color: #409EFF;
  font-weight: bold;
}

.calendar-cell.has-note {
  background-color: rgba(103, 194, 58, 0.1);
}

.calendar-cell.plan-fitness {
  background-color: rgba(103, 194, 58, 0.15);
  border-left: 3px solid #67C23A;
}

.calendar-cell.plan-diet {
  background-color: rgba(64, 158, 255, 0.15);
  border-left: 3px solid #409EFF;
}

.calendar-cell.plan-sleep {
  background-color: rgba(230, 162, 60, 0.15);
  border-left: 3px solid #E6A23C;
}

.calendar-cell.plan-health {
  background-color: rgba(245, 108, 108, 0.15);
  border-left: 3px solid #F56C6C;
}

.calendar-cell.plan-other {
  background-color: rgba(144, 147, 153, 0.15);
  border-left: 3px solid #909399;
}

.calendar-cell.has-note::after {
  content: '';
  position: absolute;
  bottom: 2px;
  width: 4px;
  height: 4px;
  background-color: #67C23A;
  border-radius: 50%;
  box-shadow: 0 0 4px rgba(103, 194, 58, 0.4);
}

.note-icon {
  position: absolute;
  top: 2px;
  right: 2px;
  font-size: 12px;
  color: #67C23A;
  text-shadow: 0 0 4px rgba(103, 194, 58, 0.4);
}

.calendar-dots {
  display: flex;
  gap: 2px;
  margin-top: 2px;
}

.dot {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  box-shadow: 0 0 4px currentColor;
}

:deep(.el-calendar) {
  background-color: transparent;
  max-height: 320px;
  overflow: hidden;
}

:deep(.el-calendar__header) {
  padding: 8px;
  border-bottom: 1px solid rgba(235, 238, 245, 0.6);
}

:deep(.el-calendar__body) {
  padding: 8px;
}

:deep(.el-calendar-table) {
  border: none;
}

:deep(.el-calendar-table th) {
  padding: 8px;
  font-size: 14px;
  color: #606266;
  font-weight: 600;
  background: rgba(245, 247, 250, 0.5);
}

:deep(.el-calendar-table td) {
  padding: 2px;
  border: none;
}

:deep(.el-calendar-day) {
  height: 60px;
  padding: 0;
}

.note-dialog-content {
  text-align: center;
  padding: 20px 25px;
  background: linear-gradient(135deg, #f8f9fa 0%, #fff 100%);
  border-radius: 8px;
}

.selected-date {
  font-size: 20px;
  color: #409EFF;
  margin-bottom: 20px;
  font-weight: 500;
  text-shadow: 0 1px 2px rgba(0,0,0,0.05);
}

:deep(.el-dialog) {
  border-radius: 15px;
  overflow: hidden;
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.1);
}

:deep(.el-dialog__header) {
  background: linear-gradient(135deg, #409EFF 0%, #67C23A 100%);
  padding: 15px 20px;
  margin: 0;
}

:deep(.el-dialog__title) {
  color: #fff;
  font-size: 18px;
  font-weight: 600;
}

:deep(.el-dialog__body) {
  padding: 0;
}

:deep(.el-dialog__footer) {
  padding: 15px 20px;
  border-top: 1px solid rgba(235, 238, 245, 0.6);
  background: rgba(245, 247, 250, 0.5);
  display: flex;
  justify-content: space-between;
}

:deep(.el-dialog__footer .el-button) {
  min-width: 80px;
}

:deep(.el-dialog__footer .el-button + .el-button) {
  margin-left: 10px;
}

:deep(.el-button--danger) {
  margin-right: auto;
}

:deep(.el-message-box) {
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
}

:deep(.el-message) {
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

:deep(.el-calendar-table td.prev) {
  visibility: hidden;
}

:deep(.el-calendar-table td.next) {
  visibility: hidden;
}

.empty-cell {
  height: 100%;
  background: transparent;
  pointer-events: none;
}

/* 自定义关闭按钮样式 */
.custom-close-btn {
  position: absolute;
  top: 15px;
  right: 15px;
  width: 36px;
  height: 36px;
  background-color: rgba(255, 255, 255, 0.9);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 20;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
  transition: all 0.3s;
}

.custom-close-btn:hover {
  background-color: #fff;
  transform: scale(1.1);
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.3);
}

.custom-close-btn i {
  font-size: 20px;
  color: #409EFF;
  font-weight: bold;
}

.custom-close-btn:hover i {
  color: #f56c6c;
}

/* 隐藏原始关闭按钮 */
.note-dialog :deep(.el-dialog__headerbtn) {
  display: none;
}

/* 增大记录输入框文字大小 */
.note-textarea :deep(.el-textarea__inner) {
  font-size: 20px;
  line-height: 1.6;
  padding: 15px;
  color: #333;
  border-radius: 8px;
  resize: none;
  height: 200px;
  border: 1px solid #dcdfe6;
}

.note-textarea :deep(.el-textarea__inner:focus) {
  border-color: #409EFF;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}

.note-textarea :deep(.el-textarea__inner::placeholder) {
  color: #909399;
  font-size: 20px;
}

/* 调整日期文字大小 */
.selected-date {
  font-size: 20px;
  color: #409EFF;
  margin-bottom: 20px;
  font-weight: 500;
  text-shadow: 0 1px 2px rgba(0,0,0,0.05);
}

/* 确保日历单元格样式正确 */
:deep(.el-calendar-table .el-calendar-day) {
  height: 40px;
  padding: 0;
}

:deep(.el-calendar-table td.prev .calendar-cell),
:deep(.el-calendar-table td.next .calendar-cell) {
  display: none;
}

.health-tip-card {
  border-radius: 15px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
  transition: all 0.3s;
  background: linear-gradient(135deg, #fff 0%, #f8f9fa 100%);
  border: 1px solid rgba(255, 255, 255, 0.8);
  backdrop-filter: blur(10px);
  position: relative;
  margin-bottom: 20px;
  transform: rotate(1deg);
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.health-tip-card:hover {
  transform: rotate(0deg) translateY(-5px);
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.12);
}

.tip-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 15px 20px;
  border-bottom: 1px solid rgba(235, 238, 245, 0.6);
  background: linear-gradient(135deg, #67C23A 0%, #409EFF 100%);
  border-radius: 15px 15px 0 0;
  position: relative;
  overflow: hidden;
}

.tip-header::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(45deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0) 100%);
  pointer-events: none;
}

.tip-header h3 {
  margin: 0;
  font-size: 20px;
  color: #fff;
  font-weight: 600;
  text-shadow: 0 1px 2px rgba(0,0,0,0.1);
}

.tip-content {
  padding: 30px;
  min-height: 200px;
  display: flex;
  flex-direction: column;
  flex-grow: 1;
  justify-content: center;
  align-items: center;
  text-align: center;
  background-color: #f9fdff;
}

.tip-icon {
  font-size: 32px;
  color: #67C23A;
  margin-bottom: 20px;
  background: rgba(103, 194, 58, 0.1);
  width: 64px;
  height: 64px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 12px rgba(103, 194, 58, 0.15);
}

.tip-content h4 {
  margin: 0 0 20px 0;
  font-size: 28px;
  color: #303133;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  text-align: center;
  position: relative;
  padding-bottom: 15px;
}

.tip-content h4::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 50px;
  height: 3px;
  background: linear-gradient(to right, #67C23A, #409EFF);
  border-radius: 3px;
}

.tip-content p {
  margin: 0;
  font-size: 18px;
  line-height: 1.8;
  color: #606266;
  flex-grow: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 6;
  -webkit-box-orient: vertical;
  text-align: center;
  padding: 0 15px;
  width: 90%;
  max-width: 600px;
}

.tip-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: auto;
  padding-top: 15px;
  border-top: 1px dashed rgba(235, 238, 245, 0.8);
}

.tip-category {
  font-size: 14px;
  color: #67C23A;
  background-color: rgba(103, 194, 58, 0.1);
  padding: 4px 10px;
  border-radius: 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 40%;
}

.tip-date {
  font-size: 14px;
  color: #909399;
  white-space: nowrap;
}

.tip-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 200px;
  color: #909399;
  background-color: #f9fdff;
  flex-grow: 1;
}

.tip-empty i {
  font-size: 40px;
  margin-bottom: 10px;
}

.tip-empty p {
  font-size: 16px;
}

.tip-header .el-button--text {
  color: #fff;
  font-weight: 500;
  transition: all 0.3s;
}

.tip-header .el-button--text:hover {
  transform: rotate(180deg);
  color: #fff;
}

.tip-header .el-button--text i {
  font-size: 16px;
  margin-right: 4px;
}

/* 响应式布局调整 */
@media screen and (max-width: 1200px) {
  .calendar-row {
    flex-direction: column;
  }
  
  .calendar-row .el-col {
    width: 100%;
  }
  
  .health-tip-card, .calendar-card {
    margin-bottom: 20px;
  }
}

/* 自定义Markdown渲染样式 */
.chat-message .markdown-list {
  padding-left: 20px !important;
  margin: 0 !important;
  list-style-position: outside !important;
  margin-bottom: -8px !important; /* 减少底部空间 */
  margin-top: -2px !important; /* 减少顶部空间 */
  padding-bottom: 0 !important;
}

.chat-message .markdown-list li {
  display: list-item !important;
  margin: 0 !important;
  line-height: 1.1 !important; /* 进一步减小行高 */
  padding: 0 !important;
  min-height: 0 !important;
}

.chat-message ul.markdown-list {
  list-style-type: disc !important;
}

.chat-message ol.markdown-list {
  list-style-type: decimal !important;
}

.chat-message .markdown-paragraph {
  margin: 1px 0 !important;
  line-height: 1.2 !important;
}

.chat-message .markdown-heading {
  margin: 8px 0 4px 0 !important;
  font-weight: bold !important;
}

.chat-message h1.markdown-heading {
  font-size: 24px !important;
}

.chat-message h2.markdown-heading {
  font-size: 22px !important;
}

.chat-message h3.markdown-heading {
  font-size: 20px !important;
}

.chat-message .markdown-blockquote {
  border-left: 3px solid #ddd !important;
  padding-left: 10px !important;
  margin: 6px 0 !important;
  color: #555 !important;
  font-style: italic !important;
}

.markdown-content {
  padding: 8px !important;
}

/* 列表样式 */
.markdown-content ul {
  list-style-type: disc !important;
  margin: 8px 0 !important;
  padding-left: 40px !important;
  display: block !important;
}

.markdown-content ol {
  list-style-type: decimal !important;
  margin: 8px 0 !important;
  padding-left: 40px !important;
  display: block !important;
}

.markdown-content li {
  display: list-item !important;
  list-style-position: outside !important;
  margin-bottom: 2px !important;
}

/* 段落和文本样式 */
.markdown-content p {
  margin: 10px 0 !important;
  display: block !important;
}

.markdown-content strong, 
.markdown-content b {
  font-weight: bold !important;
}

.markdown-content em,
.markdown-content i {
  font-style: italic !important;
}

/* 特殊字符和标记 */
.markdown-content code {
  background-color: rgba(0, 0, 0, 0.05) !important;
  border-radius: 3px !important;
  padding: 2px 4px !important;
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace !important;
}

.markdown-content pre {
  background-color: #f6f8fa !important;
  border-radius: 6px !important;
  padding: 16px !important;
  overflow: auto !important;
  margin: 16px 0 !important;
}

.markdown-content pre code {
  background-color: transparent !important;
  padding: 0 !important;
  margin: 0 !important;
  display: block !important;
  overflow-x: auto !important;
}

.markdown-content blockquote {
  border-left: 4px solid #ddd !important;
  padding: 0 16px !important;
  margin: 16px 0 !important;
  color: #555 !important;
  font-style: italic !important;
}

/* 确保所有列表项标记都正确显示 */
.markdown-content li::marker {
  color: inherit !important;
}

/* 助手消息专用样式 */
.assistant-message {
  display: block;
  width: 100%;
}

.assistant-message p, 
.assistant-message ul, 
.assistant-message ol, 
.assistant-message blockquote {
  margin-bottom: 0 !important;
  margin-top: 0 !important;
}

.assistant-message ul.markdown-list, 
.assistant-message ol.markdown-list {
  margin-top: 0 !important;
  margin-bottom: 0 !important;
}

/* 确保无序列表前后只有一个换行 */
.assistant-message p + ul.markdown-list,
.assistant-message p + ol.markdown-list {
  margin-top: -12px !important;
}

.assistant-message ul.markdown-list + p,
.assistant-message ol.markdown-list + p {
  margin-top: -12px !important;
}

/* 减小相邻列表的间距 */
.assistant-message ul.markdown-list + ul.markdown-list,
.assistant-message ol.markdown-list + ol.markdown-list,
.assistant-message ul.markdown-list + ol.markdown-list,
.assistant-message ol.markdown-list + ul.markdown-list {
  margin-top: -10px !important;
  padding-top: 0 !important;
  margin-bottom: 0 !important;
  border-top: 0 !important;
}

/* 特别处理相邻的不同类型列表 */
.adjacent-list {
  margin-top: -10px !important;
  padding-top: 0 !important;
  margin-bottom: 0 !important;
  border-top: 0 !important;
}

/* 进一步减小列表内部的间距 */
.chat-message .markdown-list li:not(:last-child) {
  margin-bottom: 0 !important;
}

/* 列表前的项目符号/数字排版优化 */
.chat-message ul.markdown-list li {
  position: relative;
}

.chat-message ul.markdown-list li::before {
  display: inline-block;
  width: 14px;
}

/* 减小带有特殊前缀符号的列表项的间距 */
.chat-message ul.markdown-list li:has(strong:first-child),
.chat-message ol.markdown-list li:has(strong:first-child) {
  margin-top: 1px !important;
}

.calendar-legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-around;
  padding: 5px;
  margin-top: 5px;
  border-top: 1px solid rgba(235, 238, 245, 0.6);
}

.legend-item {
  display: flex;
  align-items: center;
  margin: 2px;
}

.legend-color {
  width: 12px;
  height: 12px;
  border-radius: 2px;
  margin-right: 5px;
}

.legend-text {
  font-size: 10px;
  color: #606266;
}

.forum-content {
  display: flex;
  flex-direction: column;
}

.forum-table-wrapper {
  background: #fff;
  border-radius: 10px;
  box-shadow: 0 2px 8px rgba(64,158,255,0.04);
  padding: 10px 0 0 0;
  margin-bottom: 10px;
}

.forum-pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 16px 0 8px 0;
  background: #fff;
  border-radius: 0 0 10px 10px;
}

.forum-btn-row {
  display: flex;
  gap: 12px;
  margin-bottom: 16px;
}

.forum-btn-row .el-button {
  margin-bottom: 0 !important;
}

.chronic-disease-content {
  height: 100%;
  display: flex;
  flex-direction: column;
  background: #f9fafc;
  padding: 20px;
  overflow: auto;
}
.chronic-disease-table-wrapper {
  background: #fff;
  border-radius: 10px;
  box-shadow: 0 2px 8px rgba(64,158,255,0.04);
  padding: 10px 0 0 0;
  margin-bottom: 10px;
  max-height: 600px;
  overflow-y: auto;
}
.chronic-disease-table-wrapper::-webkit-scrollbar {
  width: 6px;
}
.chronic-disease-table-wrapper::-webkit-scrollbar-thumb {
  background-color: #909399;
  border-radius: 3px;
}
.chronic-disease-table-wrapper::-webkit-scrollbar-track {
  background-color: #f5f7fa;
  border-radius: 3px;
}
</style> 